package io.chenglicun.modules.data.service.statistics.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.chenglicun.common.service.impl.CrudServiceImpl;
import io.chenglicun.common.utils.ConvertUtils;
import io.chenglicun.common.utils.DateUtils;
import io.chenglicun.modules.data.dao.statistics.DataDayStatisticsDao;
import io.chenglicun.modules.data.dto.statistics.DataTimeStatisticsDTO;
import io.chenglicun.modules.data.entity.statistics.DataDayStatisticsEntity;
import io.chenglicun.modules.data.param.DataDayStatisticsParam;
import io.chenglicun.modules.data.service.statistics.DataDayStatisticsService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 日时间统计数据
 *
 * @author pipi 1151485299@qq.com
 * @since 1.0 2024-03-01
 */
@Service
public class DataDayStatisticsServiceImpl extends CrudServiceImpl<DataDayStatisticsDao, DataDayStatisticsEntity, DataTimeStatisticsDTO> implements DataDayStatisticsService {


    @Override
    public List<DataTimeStatisticsDTO> selectByTime(DataDayStatisticsParam param) {
        List<DataDayStatisticsEntity> datas = baseDao.selectList(param.buildQueryWrapper());

        return buildData(datas, param.getTime());
    }


    @Override
    public QueryWrapper<DataDayStatisticsEntity> getWrapper(Map<String, Object> params) {
        return null;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(DataTimeStatisticsDTO dto) {
        DataDayStatisticsEntity entity = ConvertUtils.sourceToTarget(dto, DataDayStatisticsEntity.class);
        entity.setDayTime(DateUtils.removeTime(dto.getTime()));
        DataDayStatisticsEntity existEntity =  getOne(getWrapper(entity));
        if (existEntity != null){
            deleteById(existEntity.getId());
        }
        baseDao.insert(entity);
    }

    public QueryWrapper<DataDayStatisticsEntity> getWrapper(DataDayStatisticsEntity entity) {
        QueryWrapper<DataDayStatisticsEntity> queryWrapper = new QueryWrapper<>();

        queryWrapper.lambda().eq(StringUtils.isNotEmpty(entity.getType()),DataDayStatisticsEntity::getType, entity.getType());
        queryWrapper.lambda().eq(entity.getDayTime() != null,DataDayStatisticsEntity::getDayTime, entity.getDayTime());

        return queryWrapper;
    }

    public List<DataTimeStatisticsDTO> buildData(List<DataDayStatisticsEntity> datas, Integer time) {
        ArrayList<DataTimeStatisticsDTO> timeDTOS = new ArrayList<>();
        if (time == 0) {
            Date firstDay = DateUtils.getFirstDayOfMonth();
            Date lastDay = DateUtils.currMonthLastDay();

            while (firstDay.before(lastDay)) {
                Date finalFirstDay = firstDay;
                DataDayStatisticsEntity statisticsEntity = datas.stream().filter(e -> e.getDayTime().equals(finalFirstDay)).findFirst().orElse(null);
                if (statisticsEntity == null){
                    DataTimeStatisticsDTO dto = new DataTimeStatisticsDTO();
                    dto.setDayData(0L);
                    dto.setTime(firstDay);
                    timeDTOS.add(dto);
                }else {
                    DataTimeStatisticsDTO statisticsDTO = ConvertUtils.sourceToTarget(statisticsEntity,DataTimeStatisticsDTO.class);
                    statisticsDTO.setTime(statisticsEntity.getDayTime());
                    timeDTOS.add(statisticsDTO);
                }
                firstDay = DateUtils.addDateDays(firstDay, 1);
            }
        }else {
            Date firstDay = DateUtils.getFirstDayOfYear();
            Date lastDay = DateUtils.getLastDayOfYear(new Date());

            while (firstDay.before(lastDay)) {
                Date finalFirstDay = firstDay;
                Date plusDay = DateUtils.addDateMonths(firstDay,1);
                Long num = datas.stream().filter(e -> e.getDayTime().compareTo(finalFirstDay) >= 0 && e.getDayTime().compareTo(plusDay) < 0).map(DataDayStatisticsEntity::getDayData).reduce(Long::sum).orElse(0L);
                DataTimeStatisticsDTO dto = new DataTimeStatisticsDTO();
                dto.setDayData(num);
                dto.setTime(firstDay);
                timeDTOS.add(dto);
                firstDay = DateUtils.addDateMonths(firstDay, 1);
            }
        }
        return timeDTOS;
    }
}